package com.sunlands.qdcy.deskmate.service;

import com.alibaba.fastjson.JSON;
import com.aliyun.oss.common.utils.DateUtil;
import com.sunlands.qdcy.deskmate.client.UserCenterService;
import com.sunlands.qdcy.deskmate.config.AppleConfig;
import com.sunlands.qdcy.deskmate.dao.pojo.OrderRecordDO;
import com.sunlands.qdcy.deskmate.dao.pojo.PaymentAppleFailRecord;
import com.sunlands.qdcy.deskmate.dao.pojo.PaymentAppleRecord;
import com.sunlands.qdcy.deskmate.dao.repository.PaymentAppleFailRecordRepository;
import com.sunlands.qdcy.deskmate.dao.repository.PaymentAppleRecordRepository;
import com.sunlands.qdcy.deskmate.enums.OrderStatus;
import com.sunlands.qdcy.deskmate.enums.PayType;
import com.sunlands.qdcy.deskmate.enums.YN;
import com.sunlands.qdcy.deskmate.exception.CheckParamException;
import com.sunlands.qdcy.deskmate.exception.SendExceptionUtil;
import com.sunlands.qdcy.deskmate.util.HttpClientUtil;
import com.sunlands.qdcy.deskmate.util.MD5;
import com.sunlands.qdcy.deskmate.util.OrderSnUtil;
import com.sunlands.qdcy.deskmate.util.SpringContextHolder;
import com.sunlands.qdcy.deskmate.vo.AppleReceiptVO;
import com.sunlands.qdcy.deskmate.vo.AppleVerifyReceiptResponse;
import com.sunlands.qdcy.deskmate.vo.Order;
import com.sunlands.qdcy.deskmate.vo.feign.VipSetMealVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author zl
 * @version 1.0
 * @date Created in 2020/4/10
 */

@Slf4j
@Service
public class ApplePayService {


    @Autowired
    private AppleConfig appleConfig;

    @Autowired
    private OrderRecordService orderRecordService;

    @Autowired
    private UserCenterService userCenterService;

    @Autowired
    private PaymentAppleRecordRepository appleRecordRepository;

    @Resource(name = "taskExecutor")
    private AsyncTaskExecutor taskExecutor;

    @Autowired
    private SendExceptionUtil sendExceptionUtil;

    @Autowired
    private PaymentAppleFailRecordRepository appleFailRecordRepository;


    @Transactional(rollbackOn = Exception.class)
    public OrderRecordDO createOrder(Order order) {
        // 这里有风险，有可能小数点后多处很长的数字
        BigDecimal totalAmount = order.getTotalAmount().setScale(2, BigDecimal.ROUND_HALF_UP);
        order.setTotalAmount(totalAmount);
        order.setOutTradeNo(OrderSnUtil.getOrderSn(PayType.IAP.getType()));

        OrderRecordDO orderRecordDO = OrderRecordDO.builder()
                .body(order.getBody())
                .outTradeNo(order.getOutTradeNo())
                .appId(appleConfig.getAppId())
                .userId(order.getUserId())
                .goodsNumber(order.getGoodsNumber())
                .totalAmount(order.getTotalAmount())
                .orderStatus(OrderStatus.PAY_WAITING.name())
                .subject(order.getSubject())
                .body(order.getBody())
                .payType(PayType.IAP.name())
                .send(YN.NO.code)
                .productId(order.getProductId())
                .build();

        return orderRecordService.save(orderRecordDO);
    }

    @Transactional(rollbackOn = Exception.class)
    public PaymentAppleRecord saveAndVerifyReceipt(AppleReceiptVO receiptVO) {

        OrderRecordDO orderRecordDO = orderRecordService.findByOutTradeNo(receiptVO.getOutTradeNo());
        if (Objects.isNull(orderRecordDO)) {
            throw new CheckParamException("未查询到下单记录！outTradeNo = " + receiptVO.getOutTradeNo());
        }

        PaymentAppleRecord old = findByOutTradeNo(receiptVO.getOutTradeNo());
        if (OrderStatus.PAY_SUCCESS.name().equals(orderRecordDO.getOrderStatus())
                || OrderStatus.RETURN.name().equals(orderRecordDO.getOrderStatus())) {
            log.warn("app支付苹果提交支付凭证，订单已经是支付状态或者退款状态,outTradeNo={}，OrderStatus={}", orderRecordDO.getOutTradeNo(), orderRecordDO.getOrderStatus());
            return old;
        }

        if (Objects.nonNull(old)) {
            old.setValid(YN.NO.code);
            appleRecordRepository.save(old);
        }
        //保存交易凭证
        PaymentAppleRecord paymentAppleRecord = save(receiptVO);
        orderRecordDO.setPayEnv(YN.YES.code.equals(paymentAppleRecord.getUseSandbox()) ? YN.NO.code : YN.YES.code);
        orderRecordService.save(orderRecordDO);
        taskExecutor.execute(() -> verifyReceipt(paymentAppleRecord, orderRecordDO));
        return paymentAppleRecord;
    }

    private PaymentAppleRecord save(AppleReceiptVO receiptVO) {
        PaymentAppleRecord paymentAppleRecord = PaymentAppleRecord.builder()
                .outTradeNo(receiptVO.getOutTradeNo())
                .receiptData(receiptVO.getReceiptData())
                .receiptDataMd5(MD5.MD5Encode(receiptVO.getReceiptData()))
                .useSandbox(receiptVO.getUseSandbox())
                .productId(receiptVO.getProductId())
                .userId(receiptVO.getUserId())
                .transactionId(receiptVO.getTransactionId())
                .valid(YN.YES.code).build();

        paymentAppleRecord = appleRecordRepository.save(paymentAppleRecord);
        return paymentAppleRecord;
    }

    public PaymentAppleRecord findByOutTradeNo(String outTradeNo) {
        PaymentAppleRecord paymentAppleRecord = PaymentAppleRecord.builder()
                .outTradeNo(outTradeNo).valid(YN.YES.code).build();
        return appleRecordRepository.findOne(Example.of(paymentAppleRecord));
    }

    /**
     * 校验苹果订单是否被退款
     *
     * @param orderRecordDO
     */
    @Transactional(rollbackOn = Exception.class)
    public void verifyReturnReceipt(OrderRecordDO orderRecordDO) {
        if (Objects.isNull(orderRecordDO)) {
            log.info("校验苹果订单是否被退款订单为空");
            return;
        }
        if (!OrderStatus.PAY_SUCCESS.name().equals(orderRecordDO.getOrderStatus())) {
            log.warn("校验苹果订单是否被退款，订单非支付状态,outTradeNo={}，OrderStatus={}", orderRecordDO.getOutTradeNo(), orderRecordDO.getOrderStatus());
            return;
        }

        PaymentAppleRecord paymentAppleRecord = findByOutTradeNo(orderRecordDO.getOutTradeNo());
        if (Objects.isNull(paymentAppleRecord)) {
            log.info("校验苹果订单是否被退款订单,未找到对应凭证（有可能是手动补的单）");
            return;
        }

        if (Objects.isNull(paymentAppleRecord.getTransactionId())) {
            log.error("校验苹果订单是否被退款订单,未对应到交易号");
            return;
        }

        String result = pullOrderStatus(paymentAppleRecord);
        AppleVerifyReceiptResponse receiptResponse = JSON.parseObject(result, AppleVerifyReceiptResponse.class);
        Integer status = receiptResponse.getStatus();
        String msg = AppleVerifyReceiptResponse.Status.by(status);
        log.info("定时校验是否有退款receiptResponse = {}", receiptResponse);
        if (AppleVerifyReceiptResponse.Status.SUCCESS.code.equals(status)) {
            List<AppleVerifyReceiptResponse.AppData> in_app = receiptResponse.getReceipt().getIn_app();
            if (!CollectionUtils.isEmpty(in_app)) {
                AppleVerifyReceiptResponse.AppData appData = null;

                for (AppleVerifyReceiptResponse.AppData data : in_app) {
                    if (data.getTransaction_id().equals(paymentAppleRecord.getTransactionId())) {
                        appData = data;
                        break;
                    }
                }

                if (Objects.isNull(appData)) {
                    log.error("校验苹果订单是否被退款订单，未找到对应的交易号 paymentAppleRecord = {}", paymentAppleRecord);
                    return;
                }

                if ((StringUtils.isNotBlank(appData.getCancellation_date())
                        || StringUtils.isNotBlank(appData.getCancellation_reason()))) { //已经退款

                    log.info("IAP用户退款 关闭对应VIP权限 paymentAppleRecord = {}", paymentAppleRecord);
                    orderRecordService.returnGoods(orderRecordDO.getOutTradeNo());
                    paymentAppleRecord.setCancellationDate(appData.getCancellation_date());
                    paymentAppleRecord.setCancellationReason(appData.getCancellation_reason());
                    if(StringUtils.isNotBlank(appData.getCancellation_date_ms())){
                        paymentAppleRecord.setCancellationDateTime(new Date(Long.parseLong(appData.getCancellation_date_ms())));
                    }
                    appleRecordRepository.save(paymentAppleRecord);

                }
            }

        } else {
            log.error("IAP校验订单状态出错，receiptResponse = {}", receiptResponse);
        }
    }

    /**
     * 校验凭证状态是否支付
     *
     * @param paymentAppleRecord
     * @param orderRecordDO
     * @return
     */
    @Transactional(rollbackOn = Exception.class)
    public OrderRecordDO verifyReceipt(PaymentAppleRecord paymentAppleRecord, OrderRecordDO orderRecordDO) {

        if (Objects.isNull(paymentAppleRecord) || Objects.isNull(orderRecordDO)) {
            return orderRecordDO;
        }

        if (OrderStatus.PAY_SUCCESS.name().equals(orderRecordDO.getOrderStatus())
                || OrderStatus.RETURN.name().equals(orderRecordDO.getOrderStatus())) {
            log.warn("核对苹果订单信息，订单已经是支付状态或者退款状态,outTradeNo={}，OrderStatus={}", orderRecordDO.getOutTradeNo(), orderRecordDO.getOrderStatus());
            return orderRecordDO;
        }

        String result = pullOrderStatus(paymentAppleRecord);
        AppleVerifyReceiptResponse receiptReponse = JSON.parseObject(result, AppleVerifyReceiptResponse.class);
        Integer status = receiptReponse.getStatus();
        String msg = AppleVerifyReceiptResponse.Status.by(status);

        paymentAppleRecord.setStatus(status);
        paymentAppleRecord.setMsg(msg);
        paymentAppleRecord.setBody(result);
        paymentAppleRecord.setUpdateTime(new Date());
        if (AppleVerifyReceiptResponse.Status.SUCCESS.code.equals(status)) {
            paymentAppleRecord.setEnvironment(receiptReponse.getEnvironment());
            orderRecordDO.setPayEnv("Sandbox".equals(receiptReponse.getEnvironment()) ? YN.NO.code : YN.YES.code);
            AppleVerifyReceiptResponse.ReceiptData receipt = receiptReponse.getReceipt();
            if (!Objects.isNull(receipt)) {
                paymentAppleRecord.setApplicationVersion(receipt.getApplication_version());
                paymentAppleRecord.setReceiptType(receipt.getReceipt_type());
                paymentAppleRecord.setOriginalApplicationVersion(receipt.getOriginal_application_version());
                paymentAppleRecord.setReceiptCreationDate(receipt.getReceipt_creation_date());
                paymentAppleRecord.setRequestDate(receipt.getRequest_date());

                List<AppleVerifyReceiptResponse.AppData> in_app = receipt.getIn_app();
                if (!CollectionUtils.isEmpty(in_app)) {
                    AppleVerifyReceiptResponse.AppData appData = null;

                    if (StringUtils.isNotBlank(paymentAppleRecord.getTransactionId())) {
                        for (AppleVerifyReceiptResponse.AppData data : in_app) {
                            if (data.getTransaction_id().equals(paymentAppleRecord.getTransactionId())) {
                                appData = data;
                                break;
                            }
                        }
                    }

                    if (Objects.isNull(appData)) {
                        for (AppleVerifyReceiptResponse.AppData data : in_app) {
                            if (data.getProduct_id().equals(paymentAppleRecord.getProductId())) {
                                appData = data;
                                break;
                            }
                        }
                    }

                    if (Objects.isNull(appData)) {
                        log.error("没有查询到对应的苹果支付订单 paymentAppleRecord = {}", paymentAppleRecord);
                        return orderRecordDO;
                    }

                    orderRecordDO.setTradeNo(appData.getTransaction_id());
                    if ("false".equals(appData.getIs_trial_period()) && StringUtils.isBlank(appData.getCancellation_date())
                            && StringUtils.isBlank(appData.getCancellation_reason())) {
                        orderRecordDO.setOrderStatus(OrderStatus.PAY_SUCCESS.name());
                        orderRecordDO.setPaymentTime(paymentAppleRecord.getCreateTime());
                        orderRecordDO.setPayEndTime(new Date());
                        orderRecordDO.setPurchaseDate(new Date(Long.parseLong(appData.getPurchase_date_ms())));
                    } else if ("false".equals(appData.getIs_trial_period()) && (StringUtils.isNotBlank(appData.getCancellation_date())
                            || StringUtils.isNotBlank(appData.getCancellation_reason()))) { //已经退款
                        orderRecordDO.setOrderStatus(OrderStatus.RETURN.name());
                        orderRecordDO.setPaymentTime(paymentAppleRecord.getCreateTime());
                        orderRecordDO.setReturnTime(new Date());
                        orderRecordDO.setPurchaseDate(new Date(Long.parseLong(appData.getPurchase_date_ms())));
                    } else if (!"false".equals(appData.getIs_trial_period())) {
                        orderRecordDO.setOrderStatus(OrderStatus.CANCEL.name());
                        orderRecordDO.setPaymentTime(paymentAppleRecord.getCreateTime());
                        orderRecordDO.setReturnTime(new Date());
                        orderRecordDO.setPurchaseDate(new Date(Long.parseLong(appData.getPurchase_date_ms())));
                    }
                    orderRecordService.save(orderRecordDO);
                    if (OrderStatus.PAY_SUCCESS.name().equals(orderRecordDO.getOrderStatus())) {
                        orderRecordService.sendGoods(paymentAppleRecord.getOutTradeNo());
                    }


                    paymentAppleRecord.setProductId(appData.getProduct_id());
                    paymentAppleRecord.setTransactionId(appData.getTransaction_id());
                    paymentAppleRecord.setQuantity(appData.getQuantity());
                    paymentAppleRecord.setTrialPeriod(appData.getIs_trial_period());
                    paymentAppleRecord.setCancellationDate(appData.getCancellation_date());
                    paymentAppleRecord.setCancellationReason(appData.getCancellation_reason());
                    if(StringUtils.isNotBlank(appData.getCancellation_date_ms())){
                        paymentAppleRecord.setCancellationDateTime(new Date(Long.parseLong(appData.getCancellation_date_ms())));
                    }
                    if(StringUtils.isNotBlank(appData.getPurchase_date_ms())){
                        paymentAppleRecord.setPurchaseDateTime(new Date(Long.parseLong(appData.getPurchase_date_ms())));
                    }
                    if(StringUtils.isNotBlank(appData.getOriginal_purchase_date_ms())){
                        paymentAppleRecord.setOriginalPurchaseDateTime(new Date(Long.parseLong(appData.getOriginal_purchase_date_ms())));
                    }

                } else {
                    log.error("苹果支付验证收据in_app数据为空,userid={},outTradeNo={},status={},msg={}", paymentAppleRecord.getUserId(), paymentAppleRecord.getOutTradeNo(), status, msg);
                }
            } else {
                log.error("苹果支付验证收据receipt数据为空,userid={},outTradeNo={},status={},msg={}", paymentAppleRecord.getUserId(), paymentAppleRecord.getOutTradeNo(), status, msg);
            }
        } else {
            log.error("苹果支付验证收据状态码不正确,userid={},outTradeNo={},status={},msg={}", paymentAppleRecord.getUserId(), paymentAppleRecord.getOutTradeNo(), status, msg);
        }
        appleRecordRepository.save(paymentAppleRecord);
        return orderRecordDO;
    }


    public String pullOrderStatus(PaymentAppleRecord paymentAppleRecord) {
        //先走正式再走沙盒
        Map<String, Object> params = new HashMap<>();
        params.put("receipt-data", paymentAppleRecord.getReceiptData());
        String body = JSON.toJSONString(params);
        log.info("苹果支付验证收据正式,userid={},outTradeNo={},useSandbox={},params={}", paymentAppleRecord.getUserId(), paymentAppleRecord.getOutTradeNo(), paymentAppleRecord.getUseSandbox(), body);
        String result = null;
        long begin = System.currentTimeMillis();
        try {
            result = HttpClientUtil.post(appleConfig.getVerifyReceiptBuyUrl(), body);
        } catch (Exception e) {
            log.error("苹果支付验证收据正式异常,userid={},outTradeNo={}", paymentAppleRecord.getUserId(), paymentAppleRecord.getOutTradeNo(), e);
            log.error("", e);
        }
        log.info("苹果支付验证收据正式结果花费{}ms,userid={},outTradeNo={},reponse={}", (System.currentTimeMillis() - begin), paymentAppleRecord.getUserId(), paymentAppleRecord.getOutTradeNo(), result);

        AppleVerifyReceiptResponse receiptReponse = JSON.parseObject(result, AppleVerifyReceiptResponse.class);
        if (AppleVerifyReceiptResponse.Status.IS_TEST_ERROR.code.equals(receiptReponse.getStatus())) {
            log.info("苹果支付验证收据沙盒,userid={},outTradeNo={},useSandbox={},params={}", paymentAppleRecord.getUserId(), paymentAppleRecord.getOutTradeNo(), paymentAppleRecord.getUseSandbox(), body);
            begin = System.currentTimeMillis();
            try {
                result = HttpClientUtil.post(appleConfig.getVerifyReceiptSandboxUrl(), body);
            } catch (Exception e) {
                log.error("苹果支付验证收据沙盒异常,userid={},outTradeNo={}", paymentAppleRecord.getUserId(), paymentAppleRecord.getOutTradeNo(), e);
                log.error("", e);
            }
            log.info("苹果支付验证收据沙盒结果花费{}ms,userid={},outTradeNo={},reponse={}", (System.currentTimeMillis() - begin), paymentAppleRecord.getUserId(), paymentAppleRecord.getOutTradeNo(), result);
            String activeProfile = SpringContextHolder.getActiveProfile();
            if ("prod".equals(activeProfile) || "pre".equals(activeProfile)) {
                sendExceptionUtil.sendException(activeProfile + "环境使用沙盒支付： userid=" + paymentAppleRecord.getUserId() + ", outTradeNo=" + paymentAppleRecord.getOutTradeNo() + ", datetime:" + DateUtil.formatAlternativeIso8601Date(new Date()));
            }

        }
        return result;
    }

//    public OrderRecordDO checkOrderStatus(String outTradeNo) {
//        OrderRecordDO orderRecordDO = orderRecordService.findByOutTradeNo(outTradeNo);
//        if (Objects.isNull(orderRecordDO)) {
//            log.error("核对苹果订单信息，订单不存在,outTradeNo={}", outTradeNo);
//            return null;
//        }
//        return checkOrderStatus(orderRecordDO);
//    }

    public OrderRecordDO checkOrderStatus(OrderRecordDO orderRecordDO) {
        if (Objects.isNull(orderRecordDO)) {
            log.error("核对苹果订单信息，订单参数为空");
            return null;
        }
        String outTradeNo = orderRecordDO.getOutTradeNo();

        PaymentAppleRecord paymentAppleRecord = findByOutTradeNo(outTradeNo);
        if (Objects.isNull(paymentAppleRecord)) {
            log.info("核对苹果订单信息，未提交支付收据,outTradeNo={}", outTradeNo);
            return orderRecordDO;
        }

        orderRecordDO = verifyReceipt(paymentAppleRecord, orderRecordDO);

        return orderRecordDO;
    }

//    public OrderRecordDO closeOrder(String outTradeNo) {
//        OrderRecordDO orderRecordDO = orderRecordService.findByOutTradeNo(outTradeNo);
//        if (Objects.isNull(orderRecordDO)) {
//            log.error("关闭苹果订单，订单不存在,outTradeNo={}", outTradeNo);
//            return null;
//        }
//
//        return closeOrder(orderRecordDO);
//    }

    public OrderRecordDO closeOrder(OrderRecordDO orderRecordDO) {
        if (Objects.isNull(orderRecordDO)) {
            log.error("关闭苹果订单，订单参数为空");
            return null;
        }

        String outTradeNo = orderRecordDO.getOutTradeNo();
        orderRecordDO = checkOrderStatus(orderRecordDO);

        if (orderRecordDO.getCreateTime().after(DateUtils.addHours(new Date(), -1))) {
            log.warn("关闭苹果订单，当前订单未超过1小时，先不取消,outTradeNo={},createTime={}", outTradeNo, orderRecordDO.getCreateTime());
            return orderRecordDO;
        }

        if (!OrderStatus.PAY_WAITING.name().equals(orderRecordDO.getOrderStatus())) {
            log.warn("关闭苹果订单，当前订单状态不能取消,outTradeNo={},orderStatus={}", outTradeNo, orderRecordDO.getOrderStatus());
            return orderRecordDO;
        }

        orderRecordDO.setOrderStatus(OrderStatus.CANCEL.name());
        orderRecordDO.setPayEndTime(new Date());
        return orderRecordService.save(orderRecordDO);
    }


    public void saveAppleFailRecord(PaymentAppleFailRecord appleFailRecord) {
        if (StringUtils.isNotBlank(appleFailRecord.getReceiptData())) {
            appleFailRecord.setReceiptDataMd5(MD5.MD5Encode(appleFailRecord.getReceiptData()));
        }
        appleFailRecord = appleFailRecordRepository.save(appleFailRecord);
    }

    public PaymentAppleFailRecord verifyFailRecord(Long id) {
        if (Objects.isNull(id)) {
            return null;
        }
        PaymentAppleFailRecord appleFailRecord = appleFailRecordRepository.findOne(id);
        if (Objects.isNull(appleFailRecord)) {
            log.error("苹果支付失败记录不存在，id={}", id);
            return null;
        }
        return verifyFailRecord(appleFailRecord);
    }

    public PaymentAppleFailRecord verifyFailRecord(PaymentAppleFailRecord appleFailRecord) {
        if (Objects.isNull(appleFailRecord)) {
            return null;
        }
        if (StringUtils.isBlank(appleFailRecord.getReceiptData()) || "receiptData".equals(appleFailRecord.getReceiptData())) {
            log.error("苹果支付失败记录 支付凭证不存在，id={}", appleFailRecord.getId());
            appleFailRecord.setHasHandled(2);
            return appleFailRecordRepository.save(appleFailRecord);
        }

        if (0 != appleFailRecord.getHasHandled()) {
            log.error("苹果支付失败记录 已经处理过，id={}", appleFailRecord.getId());
            return appleFailRecord;
        }
        String outTradeNo = null;
        if (!"outTradeNo".equals(appleFailRecord.getOutTradeNo())) {
            outTradeNo = appleFailRecord.getOutTradeNo();
        }

        PaymentAppleRecord paymentRecord = new PaymentAppleRecord();
        BeanUtils.copyProperties(appleFailRecord, paymentRecord);

        String result = pullOrderStatus(paymentRecord);
        AppleVerifyReceiptResponse receiptReponse = JSON.parseObject(result, AppleVerifyReceiptResponse.class);
        Integer status = receiptReponse.getStatus();
        String msg = AppleVerifyReceiptResponse.Status.by(status);

        appleFailRecord.setStatus(status);
        appleFailRecord.setMsg(msg);
        appleFailRecord.setBody(result);
        Map<String, AppleVerifyReceiptResponse.AppData> transactionIdMap = new HashMap<>();
        if (AppleVerifyReceiptResponse.Status.SUCCESS.code.equals(status)) {
            appleFailRecord.setEnvironment(receiptReponse.getEnvironment());
            AppleVerifyReceiptResponse.ReceiptData receipt = receiptReponse.getReceipt();
            if (!Objects.isNull(receipt)) {
                appleFailRecord.setApplicationVersion(receipt.getApplication_version());
                appleFailRecord.setReceiptType(receipt.getReceipt_type());
                appleFailRecord.setOriginalApplicationVersion(receipt.getOriginal_application_version());
                appleFailRecord.setReceiptCreationDate(receipt.getReceipt_creation_date());
                appleFailRecord.setRequestDate(receipt.getRequest_date());

                List<AppleVerifyReceiptResponse.AppData> in_app = receipt.getIn_app();
                if (!CollectionUtils.isEmpty(in_app)) {
                    for (int i = 0; i < in_app.size(); i++) {
                        AppleVerifyReceiptResponse.AppData data = in_app.get(i);
                        if (Objects.nonNull(appleFailRecord.getProductId())) {
                            if (!data.getProduct_id().equals(appleFailRecord.getProductId())) {
                                continue;
                            }
                        }
                        if ("false".equals(data.getIs_trial_period()) && StringUtils.isBlank(data.getCancellation_date())
                                && StringUtils.isBlank(data.getCancellation_reason())) {
                            transactionIdMap.put(data.getTransaction_id(), data);
                        }
                    }

                } else {
                    log.error("苹果支付失败记录验证收据in_app数据为空,userid={},outTradeNo={},status={},msg={}", appleFailRecord.getUserId(), appleFailRecord.getOutTradeNo(), status, msg);
                }
            } else {
                log.error("苹果支付失败记录收据receipt数据为空,userid={},outTradeNo={},status={},msg={}", appleFailRecord.getUserId(), appleFailRecord.getOutTradeNo(), status, msg);
            }
        }

        appleFailRecord = appleFailRecordRepository.save(appleFailRecord);
        if (!AppleVerifyReceiptResponse.Status.SUCCESS.code.equals(status)) {
            return appleFailRecord;
        }

        if (CollectionUtils.isEmpty(transactionIdMap)) {
            log.error("苹果支付失败记录验证收据数据已经处理完，in_app数据已经过期或者退款,userid={},receiptDataMd5={}", appleFailRecord.getUserId(), appleFailRecord.getReceiptDataMd5());
            return appleFailRecord;
        }
        List<OrderRecordDO> allOrder = new ArrayList<>();
        if (StringUtils.isNotBlank(outTradeNo)) {
            OrderRecordDO orderRecordDO = orderRecordService.findByOutTradeNo(outTradeNo);
            if (Objects.nonNull(orderRecordDO)) {
                allOrder.add(orderRecordDO);
            }
        } else {
            allOrder = orderRecordService.findAllByUserId(appleFailRecord.getUserId());
        }

        if (CollectionUtils.isEmpty(allOrder)) {
            log.error("苹果支付失败记录验证收据数据已经处理完，查不到补单的数据,userid={},receiptDataMd5={}", appleFailRecord.getUserId(), appleFailRecord.getReceiptDataMd5());
            appleFailRecord.setHasHandled(-2);
            appleFailRecordRepository.save(appleFailRecord);
            return appleFailRecord;
        }

        allOrder = allOrder.stream().filter(o -> PayType.IAP.name().equals(o.getPayType())).collect(Collectors.toList());
        Map<String, OrderRecordDO> needHanderOrder = allOrder.stream().filter(o -> OrderStatus.CANCEL.name().equals(o.getOrderStatus())
                || OrderStatus.PAY_WAITING.name().equals(o.getOrderStatus())).collect(Collectors.toMap(OrderRecordDO::getOutTradeNo, a -> a, (k1, k2) -> k1));
        Map<Long, List<OrderRecordDO>> needHanderGoodsOrderMap = needHanderOrder.values().stream().collect(Collectors.groupingBy(OrderRecordDO::getGoodsNumber));
        Map<String, OrderRecordDO> successRefundOrder = allOrder.stream().filter(o -> OrderStatus.PAY_SUCCESS.name().equals(o.getOrderStatus())
                || OrderStatus.RETURN.name().equals(o.getOrderStatus())).collect(Collectors.toMap(OrderRecordDO::getOutTradeNo, a -> a, (k1, k2) -> k1));
        if (CollectionUtils.isEmpty(needHanderOrder)) {
            log.error("苹果支付失败记录验证收据数据已经处理完，目前已经没有需要补单的数据,userid={},receiptDataMd5={}", appleFailRecord.getUserId(), appleFailRecord.getReceiptDataMd5());
            appleFailRecord.setHasHandled(-2);
            appleFailRecordRepository.save(appleFailRecord);
            return appleFailRecord;
        }

        for (OrderRecordDO orderRecordDO : allOrder) {
            if (StringUtils.isNotBlank(orderRecordDO.getTradeNo()) && (OrderStatus.PAY_SUCCESS.name().equals(orderRecordDO.getOrderStatus())
                    || OrderStatus.RETURN.name().equals(orderRecordDO.getOrderStatus()))) {
                transactionIdMap.remove(orderRecordDO.getTradeNo());
                successRefundOrder.remove(orderRecordDO.getOutTradeNo());
            }
        }

        if (CollectionUtils.isEmpty(transactionIdMap)) {
            log.error("苹果支付失败记录验证收据数据已经处理完，userid={},receiptDataMd5={}", appleFailRecord.getUserId(), appleFailRecord.getReceiptDataMd5());
            appleFailRecord.setHasHandled(-2);
            appleFailRecordRepository.save(appleFailRecord);
            return appleFailRecord;
        }

        Map<String, List<AppleVerifyReceiptResponse.AppData>> productIdMap = transactionIdMap.values().stream().collect(Collectors.groupingBy(AppleVerifyReceiptResponse.AppData::getProduct_id));

        List<VipSetMealVO> vipSetMealVOS = userCenterService.listVipSetMeal("IPhone").getData();
        log.info("vipSetMealVOS :{}", vipSetMealVOS);
        Map<String, List<VipSetMealVO>> listMap = vipSetMealVOS.stream().collect(Collectors.groupingBy(o -> o.getProductId()));

        Map<Long, List<AppleVerifyReceiptResponse.AppData>> goodsIdDataMap = new HashMap<>();
        productIdMap.forEach((k, v) -> {
            List<VipSetMealVO> tmp = listMap.get(k);
            if (CollectionUtils.isEmpty(tmp)) {
                log.error("verifyFailRecord productId 不存在{}", k);
            }
            tmp.forEach(o -> goodsIdDataMap.put(o.getId(), v));
        });

        Iterator<Map.Entry<String, OrderRecordDO>> iterator = successRefundOrder.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, OrderRecordDO> entry = iterator.next();
            OrderRecordDO orderRecordDO = entry.getValue();
            if (goodsIdDataMap.containsKey(orderRecordDO.getGoodsNumber())) {
                List<AppleVerifyReceiptResponse.AppData> list = goodsIdDataMap.get(orderRecordDO.getGoodsNumber());
                if (!CollectionUtils.isEmpty(list)) {
                    list.sort(Comparator.comparing(AppleVerifyReceiptResponse.AppData::getPurchase_date_ms));
                    list.remove(0);
                }

                if (CollectionUtils.isEmpty(list)) {
                    goodsIdDataMap.remove(orderRecordDO.getGoodsNumber());
                    iterator.remove();
                    continue;
                }
                goodsIdDataMap.put(orderRecordDO.getGoodsNumber(), list);
            }
        }

        if (CollectionUtils.isEmpty(goodsIdDataMap)) {
            log.error("苹果支付失败记录验证收据数据已经处理完，userid={},receiptDataMd5={}", appleFailRecord.getUserId(), appleFailRecord.getReceiptDataMd5());
            appleFailRecord.setHasHandled(-2);
            appleFailRecordRepository.save(appleFailRecord);
            return appleFailRecord;
        }
        List<Pair<OrderRecordDO, AppleVerifyReceiptResponse.AppData>> needHandleOrder = new ArrayList<>();
        Iterator<Map.Entry<Long, List<AppleVerifyReceiptResponse.AppData>>> goodsIdDataIt = goodsIdDataMap.entrySet().iterator();
        while (goodsIdDataIt.hasNext()) {
            Map.Entry<Long, List<AppleVerifyReceiptResponse.AppData>> entry = goodsIdDataIt.next();
            Long goodsId = entry.getKey();
            List<AppleVerifyReceiptResponse.AppData> appDataList = entry.getValue();
            List<OrderRecordDO> orderList = needHanderGoodsOrderMap.get(goodsId);
            if (CollectionUtils.isEmpty(orderList)) {
                log.error("苹果支付失败记录验证收据数据，找不到订单，userid={},receiptDataMd5={}", appleFailRecord.getUserId(), appleFailRecord.getReceiptDataMd5());
                sendExceptionUtil.sendException("苹果支付失败记录验证收据数据，找不到订单， userid=" + appleFailRecord.getUserId() + ", outTradeNo=" + appleFailRecord.getOutTradeNo() + ", receiptDataMd5=" + appleFailRecord.getReceiptDataMd5() + ", datetime:" + DateUtil.formatAlternativeIso8601Date(new Date()));
                continue;
            }
            orderList.sort(Comparator.comparing(OrderRecordDO::getCreateTime).reversed());
            appDataList.sort(Comparator.comparing(AppleVerifyReceiptResponse.AppData::getPurchase_date_ms).reversed());

            for (int i = 0; i < appDataList.size(); i++) {
                if (i < orderList.size()) {
                    OrderRecordDO orderRecordDO = orderList.get(i);
                    AppleVerifyReceiptResponse.AppData appData = appDataList.get(i);
                    needHandleOrder.add(Pair.of(orderRecordDO, appData));
                }
            }

        }

        for (Pair<OrderRecordDO, AppleVerifyReceiptResponse.AppData> pair : needHandleOrder) {
            AppleReceiptVO receiptVO = new AppleReceiptVO();
            receiptVO.setUserId(appleFailRecord.getUserId());
            receiptVO.setReceiptData(appleFailRecord.getReceiptData());
            receiptVO.setUseSandbox("Sandbox".equals(appleFailRecord.getEnvironment()) ? YN.YES.code : YN.NO.code);
            receiptVO.setOutTradeNo(pair.getLeft().getOutTradeNo());
            receiptVO.setProductId(pair.getRight().getProduct_id());
            receiptVO.setTransactionId(pair.getRight().getTransaction_id());
            log.error("苹果支付失败记录验证收据数据，提交补单数据，userid={},receiptDataMd5={}，data={}", appleFailRecord.getUserId(), appleFailRecord.getReceiptDataMd5(), JSON.toJSONString(receiptVO));
            saveAndVerifyReceipt(receiptVO);
        }

        appleFailRecord.setHasHandled(2);
        appleFailRecordRepository.save(appleFailRecord);
        return appleFailRecord;
    }

    public void verifyALlFailRecord() {

        PaymentAppleFailRecord appleFailRecord = PaymentAppleFailRecord.builder()
                .hasHandled(0).build();

        List<PaymentAppleFailRecord> failRecordList = appleFailRecordRepository.findAll(Example.of(appleFailRecord));
        if (CollectionUtils.isEmpty(failRecordList)) {
            return;
        }
        for (int i = 0; i < failRecordList.size(); i++) {
            try {
                verifyFailRecord(failRecordList.get(i));
            } catch (Exception e) {
                log.error("verifyALlFailRecord error,paymentAppleFailRecord={}", JSON.toJSONString(failRecordList.get(i)));
                log.error("verifyALlFailRecord ", e);
            }
        }
    }


//    public String getStatusMsg(Integer status) {
//        if (Objects.isNull(status)) {
//            return null;
//        }
//        String msg = null;
//        switch (status) {
//            case 21000:
//                msg = "对App Store的请求不是使用HTTP POST请求方法发出的。";
//                break;
//            case 21001:
//                msg = "此状态代码不再由App Store发送。";
//                break;
//            case 21002:
//                msg = "receipt-data属性中的数据格式不正确或服务遇到临时问题。再试一次。";
//                break;
//            case 21003:
//                msg = "这张收据不能被认证。";
//                break;
//            case 21004:
//                msg = "提供的共享秘密与您的帐户文件上的共享秘密不匹配。";
//                break;
//            case 21005:
//                msg = "收据服务器暂时无法提供收据。再试一次。";
//                break;
//            case 21006:
//                msg = "此收据有效，但订阅已过期。当此状态码返回到您的服务器时，接收数据也将被解码并作为响应的一部分返回。只返回iOS 6风格的自动更新订阅的交易收据。";
//                break;
//            case 21007:
//                msg = "这个收据来自测试环境，但是它被发送到生产环境进行验证。";
//                break;
//            case 21008:
//                msg = "这个收据来自生产环境，但是它被发送到测试环境进行验证。";
//                break;
//            case 21009:
//                msg = "内部数据访问错误。稍后再试。";
//                break;
//            case 21010:
//                msg = "用户帐户无法找到或已被删除。";
//                break;
//            default:
//                msg = status.toString();
//        }
//
//        return msg;
//    }

}
